package com.example.patient.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.RandomUtil;
import com.example.common.entity.*;
import com.example.common.support.ApiException;
import com.example.common.utils.CheckUtils;
import com.example.common.utils.IdUtils;
import com.example.common.utils.SmsUtils;
import com.example.common.utils.UIDUtils;
import com.example.patient.dto.req.*;
import com.example.patient.dto.resp.*;
import com.example.patient.jpa.*;
import com.example.patient.mapper.UserMapper;
import com.example.patient.service.UserService;
import com.example.patient.utils.IdNoUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author wxy
 * @Date 2021/1/18 14:21
 * @Version 1.0
 */
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UIDUtils uidUtils;

    @Resource
    private UserMapper userMapper;

    @Resource
    private HospitalRepository hospitalRepository;
    @Resource
    private ClientBaseInfoRepository clientBaseInfoRepository;
    @Resource
    private MsgConfigRepository msgConfigRepository;
    @Resource
    private ClientPatientsInfoRepository clientPatientsInfoRepository;
    @Resource
    private AddressRepository addressRepository;
    @Resource
    private FollowrQuestionMainRepository followrQuestionMainRepository;
    @Resource
    private QuestionRepository questionRepository;
    @Resource
    private AnswerRepository answerRepository;
    @Resource
    private IdNoUtils idNoUtils;

    /**
     * 医院服务电话
     */
    @Override
    public Object CenterData() {
        Hospital hospital = hospitalRepository.findFirstByOrderByIdDesc();
        CheckUtils.checkNull(hospital, new ApiException(1, "未查询到数据"));
        return hospital.getTel();
    }

    /**
     * 修改用户
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "jpaTransactionManager")
    public Object SetUserInfo(SetUserInfoReq req) {
        CheckUtils.checkNull(req, new ApiException(1, "对象不能为空"));
        String nickName = CheckUtils.checkNullReturn(req.getNickName(), new ApiException(1, "用户昵称不能为空"));
        String header = CheckUtils.checkNullReturn(req.getHeader(), new ApiException(1, "用户头像不能为空"));
        Long uid = uidUtils.getUid();
        ClientBaseInfo clientBaseInfo = clientBaseInfoRepository.findById(uid).orElseThrow(() -> new ApiException(1, "用户不存在"));
        clientBaseInfo.setNickName(nickName);
        clientBaseInfo.setHeader(header);
        clientBaseInfoRepository.save(clientBaseInfo);
        return null;
    }

    /**
     * 关注医生列表
     */
    @Override
    public PageInfo<DCRelationListsResp> DCRelationLists(DCRelationListsReq req) {
        CheckUtils.checkNull(req, new ApiException(1, "对象不能为空"));
        Integer pageNumber = CheckUtils.checkNullReturn(req.getPage(), new ApiException(1, "分页页数不能为空"));
        Integer pageSize = CheckUtils.checkNullReturn(req.getLimit(), new ApiException(1, "分页条数不能为空"));
        Long uid = uidUtils.getUid();
        return PageHelper.startPage(pageNumber, pageSize).doSelectPageInfo(() -> userMapper.DCRelationLists(uid));
    }

    /**
     * 就诊人列表
     */
    @Override
    public Map<String, Object> PatientLists(PageReq req) {
        Map<String, Object> result = new HashMap<>();
        Long uid = uidUtils.getUid();
        List<PatientListsResp> data = userMapper.PatientLists(uid, (req.getPage() - 1) * req.getLimit(), req.getLimit());
        Long count = userMapper.countPatientLists(uid);
        List<PatientListsResp> list = data.stream().peek(p -> {
            Boolean isChild = DateUtil.betweenYear(p.getBirthday(), new Date(), Boolean.FALSE) <= 6L ? Boolean.TRUE : Boolean.FALSE;
            String idNumShow = IdcardUtil.hide(p.getIdNo(), 7, 15);
            p.setIsChild(isChild);
            p.setIdNumShow(idNumShow);
        }).collect(Collectors.toList());
        result.put("total",count);
        result.put("list",list);
        return result;
    }

    /**
     * 短信验证
     */
    @Override
    public Object PatientSendSMS(PatientSendSMSReq req) {
        CheckUtils.checkNull(req, new ApiException(1, "对象不能为空"));
        String tel = CheckUtils.checkNullReturn(req.getTel(), new ApiException(1, "电话不能为空"));
        MsgConfig msgConfig = msgConfigRepository.findById("Client_LoginCode").orElseThrow(() -> new ApiException(1, "未查询到数据"));
        String templateId = msgConfig.getTemplateId();
        String code = RandomUtil.randomNumbers(6);
        SmsUtils.sendSmsMessage(tel, Collections.singletonList(code), templateId);

        return code;
    }

    /**
     * 就诊人详情
     */
    @Override
    public PatientDetailResp PatientDetail(PatientDetailReq req) {
        CheckUtils.checkNull(req, new ApiException(1, "对象不能为空"));
        Long pid = CheckUtils.checkNullReturn(req.getPID(), new ApiException(1, "患者id不能为空"));
        Long uid = uidUtils.getUid();

        ClientPatientsInfo clientPatientsInfo = clientPatientsInfoRepository.findById(pid).orElseThrow(() -> new ApiException(1, "未查询到数据"));
        if (!uid.equals(clientPatientsInfo.getClientID())) {
            throw new ApiException(1, "患者不存在");
        }
        PatientDetailResp resp = new PatientDetailResp();
        resp.setName(clientPatientsInfo.getName());
        resp.setIdNo(clientPatientsInfo.getIdNo());
        resp.setNation(clientPatientsInfo.getNation());
        resp.setPhone(clientPatientsInfo.getPhone());
        resp.setIsChild(DateUtil.betweenYear(clientPatientsInfo.getBirthday(), new Date(), Boolean.FALSE) <= 6L);
        resp.setRelationship(clientPatientsInfo.getRelationship());
        resp.setGuardianName(clientPatientsInfo.getGuardianName());
        resp.setGuardianIdNo(clientPatientsInfo.getGuardianIDNO());
        resp.setGuardianNation(clientPatientsInfo.getGuardianNation());
        resp.setDefaultBit(clientPatientsInfo.getDefaultBit());
        return resp;
    }

    @Value("${checkCanFace}")
    Boolean checkCanFace;
    /**
     * 提交就诊人
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "jpaTransactionManager")
    public Object SubmitPatient(SubmitPatientReq req) {
        CheckUtils.checkNull(req, new ApiException(1, "对象不能为空"));
        Long uid = uidUtils.getUid();

        Long pid = req.getPID();
        String name = req.getName();
        String idNo = req.getIDNO();
        String nation = req.getNation();
        String phone = req.getPhone();
        String relationship = req.getRelationship();
        String guardianName = req.getGuardianName();
        String guardianIDNO = req.getGuardianIDNO();
        String guardianNation = req.getGuardianNation();
        Boolean defaultBit = req.getDefault();

        if (!IdcardUtil.isValidCard18(idNo)) {
            throw new ApiException(1, "身份证号有误");
        }
           
        if(!checkCanFace && !idNoUtils.docheck(idNo, name)){
            throw new ApiException(1, "姓名、身份号认证失败");
        }

        DateTime birthday = IdcardUtil.getBirthDate(idNo);
        int age = IdcardUtil.getAgeByIdCard(idNo);
        if (age <= 6) {
            if (StringUtils.isEmpty(relationship) || StringUtils.isEmpty(guardianName) || StringUtils.isEmpty(guardianIDNO) || StringUtils.isEmpty(guardianNation)) {
                throw new ApiException(1, "低龄儿童，请添加监护人信息");
            }
            if (!IdcardUtil.isValidCard18(guardianIDNO)) {
                throw new ApiException(1, "监护人身份证号有误");
            }
        }
        if (defaultBit) {
            ClientPatientsInfo clientPatientsInfo = clientPatientsInfoRepository.findFirstByClientIDAndDefaultBit(uid, Boolean.TRUE);
            if (null != clientPatientsInfo) {
                clientPatientsInfo.setDefaultBit(Boolean.FALSE);
                clientPatientsInfoRepository.save(clientPatientsInfo);
            }
        }
        if (pid == 0) {
            Long count = clientPatientsInfoRepository.countByIdNoAndClientIDAndDisable(idNo, uid, Boolean.FALSE);
            if (count > 0) {
                throw new ApiException(1, "患者已存在，请检查");
            }
            ClientBaseInfo clientBaseInfo = clientBaseInfoRepository.findById(uid).orElseThrow(() -> new ApiException(1, "未查询到数据"));
            ClientPatientsInfo clientPatientsInfo = new ClientPatientsInfo();
            clientPatientsInfo.setPid(IdUtils.generateId());
            clientPatientsInfo.setHeader(clientBaseInfo.getHeader());
            clientPatientsInfo.setClientID(uid);
            clientPatientsInfo.setName(name);
            clientPatientsInfo.setSex(1 == IdcardUtil.getGenderByIdCard(idNo) ? "男" : "女");
            clientPatientsInfo.setBirthday(birthday);
            clientPatientsInfo.setIdNo(idNo);
            clientPatientsInfo.setNation(nation);
            clientPatientsInfo.setPhone(phone);
            clientPatientsInfo.setRelationship(relationship);
            clientPatientsInfo.setGuardianName(guardianName);
            clientPatientsInfo.setGuardianIDNO(guardianIDNO);
            clientPatientsInfo.setGuardianNation(guardianNation);
            clientPatientsInfo.setDefaultBit(defaultBit);
            clientPatientsInfo.setDisable(Boolean.FALSE);
            clientPatientsInfoRepository.save(clientPatientsInfo);
        } else {
            ClientPatientsInfo clientPatientsInfo = clientPatientsInfoRepository.findById(pid).orElseThrow(() -> new ApiException(1, "错误的请求参数"));
            if(!clientPatientsInfo.getIdNo().equals(idNo)){
                int count = clientPatientsInfoRepository.countByIdNoAndClientIDAndDisableAndPidNot(idNo, uid, Boolean.FALSE, pid);
                if(count > 0)
                    throw new ApiException(1, "存在相同身份证号的患者，请检查");
            }
            clientPatientsInfo.setName(name);
            clientPatientsInfo.setIdNo(idNo);
            clientPatientsInfo.setSex(1 == IdcardUtil.getGenderByIdCard(idNo) ? "男" : "女");
            clientPatientsInfo.setBirthday(birthday);
            clientPatientsInfo.setNation(nation);
            clientPatientsInfo.setPhone(phone);
            clientPatientsInfo.setRelationship(relationship);
            clientPatientsInfo.setGuardianName(guardianName);
            clientPatientsInfo.setGuardianIDNO(guardianIDNO);
            clientPatientsInfo.setGuardianNation(guardianNation);
            clientPatientsInfo.setDefaultBit(defaultBit);
            clientPatientsInfoRepository.save(clientPatientsInfo);
        }
        return null;
    }

    /**
     * 删除就诊人
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "jpaTransactionManager")
    public Object DelPatient(DelPatientReq req) {
        CheckUtils.checkNull(req, new ApiException(1, "对象不能为空"));
        Long pid = CheckUtils.checkNullReturn(req.getPID(), new ApiException(1, "患者id不能为空"));
        ClientPatientsInfo clientPatientsInfo = clientPatientsInfoRepository.findById(pid).orElseThrow(() -> new ApiException(1, "患者不存在"));
        clientPatientsInfo.setDisable(Boolean.TRUE);
        clientPatientsInfoRepository.save(clientPatientsInfo);
        return null;
    }

    /**
     * 地址管理列表
     */
    @Override
    public List<AddressListsResp> AddressLists() {
        Long uid = uidUtils.getUid();
        List<AddressListsResp> addressListsResps = userMapper.AddressLists(uid);
        List<AddressListsResp> first=new ArrayList<>();
        List<AddressListsResp> others=new ArrayList<>();
        addressListsResps.stream().forEach(address -> {
            if (address.getDefaultBit()){
                first.add(address);
            }else {
                others.add(address);
            }
        });
        first.addAll(others);
        return first;
    }

    /**
     * 地址详情
     */
    @Override
    public AddressDetailResp AddressDetail(AddressDetailReq req) {
        CheckUtils.checkNull(req, new ApiException(1, "对象不能为空"));
        Long id = CheckUtils.checkNullReturn(req.getID(), new ApiException(1, "地址id不能为空"));
        Long uid = uidUtils.getUid();
        Address address = addressRepository.findById(id).orElseThrow(() -> new ApiException(1, "未查询到数据"));
        if (!uid.equals(address.getClientId())) {
            throw new ApiException(1, "地址不存在");
        }
        AddressDetailResp resp = new AddressDetailResp();
        resp.setId(address.getId());
        resp.setCName(address.getCName());
        resp.setCPhone(address.getCPhone());
        resp.setCDetail(address.getCDetail());
        resp.setDefaultBit(address.getDefaultBit());
        resp.setArea(address.getArea());
        return resp;
    }

    /**
     * 添加和修改地址
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "jpaTransactionManager")
    public Object SaveAddress(SaveAddressReq req) {
        Long uid = uidUtils.getUid();
        Long id = req.getID();
        String cName = req.getCName();
        String cPhone = req.getCPhone();
        String cDetail = req.getCDetail();
        String cAddress = req.getCAddress();
        Boolean defaultBit = req.getDefault();
        String area = req.getArea();
        if (defaultBit) {
            Address address = addressRepository.findFirstByClientIdAndDefaultBit(uid, Boolean.TRUE);
            if (null != address) {
                address.setDefaultBit(Boolean.FALSE);
                addressRepository.save(address);
            }
        }
        Address address;
        if (id == 0) {
            address = new Address();
            address.setId(IdUtils.generateId());
            address.setClientId(uid);
            address.setCName(cName);
            address.setCPhone(cPhone);
            address.setCDetail(cDetail);
            address.setCAddress(cAddress);
            address.setDefaultBit(defaultBit);
            address.setArea(area);
            addressRepository.save(address);
        } else {
            address = addressRepository.findById(id).orElseThrow(() -> new ApiException(1, "错误的请求参数"));
            address.setCName(cName);
            address.setCPhone(cPhone);
            address.setCDetail(cDetail);
            address.setCAddress(cAddress);
            address.setDefaultBit(defaultBit);
            address.setArea(area);
            addressRepository.save(address);
        }
        return null;
    }

    /**
     * 删除地址
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "jpaTransactionManager")
    public Object DelAddress(DelAddressReq req) {
        CheckUtils.checkNull(req, new ApiException(1, "对象不能为空"));
        Long id = CheckUtils.checkNullReturn(req.getID(), new ApiException(1, "地址id不能为空"));
        Long uid = uidUtils.getUid();
        Address address = addressRepository.findById(id).orElseThrow(() -> new ApiException(1, "地址不存在"));
        if (address.getDefaultBit()) {
            Address newAddress = addressRepository.findFirstByClientIdAndDefaultBit(uid, Boolean.FALSE);
            if(ObjectUtils.isEmpty(newAddress)){
                throw new ApiException(1,"当前删除的地址为仅剩唯一的地址,请先添加其他地址再进行删除");
            }
            newAddress.setDefaultBit(Boolean.TRUE);
            addressRepository.save(newAddress);
        }
        addressRepository.delete(address);
        return null;
    }

    /**
     * 随访列表
     */
    @Override
    public List<MyFollowrListResp> MyFollowrList() {
        Long uid = uidUtils.getUid();
        List<MyFollowrListResp> dataList = userMapper.findMyFollowrList(uid);
        dataList = dataList.stream().peek(p -> {
            long age = DateUtil.betweenYear(p.getBirthday(), new Date(), Boolean.FALSE);
            p.setAge((int) age);
        }).collect(Collectors.toList());
        return dataList;
    }

    /**
     * 随访详情
     */
    @Override
    public MyFollowrDetailResp MyFollowrDetail(MyFollowrDetailReq req) {
        CheckUtils.checkNull(req, new ApiException(1, "对象不能为空"));
        Long fid = CheckUtils.checkNullReturn(req.getFID(), new ApiException(1, "随访id不能为空"));
        FollowrQuestionMain followrQuestionMain = followrQuestionMainRepository.findById(fid).orElseThrow(() -> new ApiException(1, "未查询到数据"));
        List<Question> questionList = questionRepository.findAllByFidOrderByQidAsc(followrQuestionMain.getFid());
        List<Answer> answerList = answerRepository.findByFid(followrQuestionMain.getFid());
        List<MyFollowrDetailResp.QAListResp> qaListRespList = new ArrayList<>();
        questionList.forEach(c -> {
            List<MyFollowrDetailResp.AnswerResp> answerRespList = answerList.stream()
                    .filter(f -> f.getQid().equals(c.getQid()))
                    .map(m -> {
                        MyFollowrDetailResp.AnswerResp answerResp = new MyFollowrDetailResp.AnswerResp();
                        answerResp.setId(m.getId());
                        answerResp.setFid(m.getFid());
                        answerResp.setAItem(m.getAItem());
                        answerResp.setChk(m.getChk());
                        return answerResp;
                    }).collect(Collectors.toList());
            MyFollowrDetailResp.QAListResp qaListResp = new MyFollowrDetailResp.QAListResp();
            qaListResp.setQContent(c.getQContent());
            qaListResp.setQType(c.getQType());
            qaListResp.setAnswer(answerRespList);
            qaListRespList.add(qaListResp);
        });
        MyFollowrDetailResp resp = new MyFollowrDetailResp();
        resp.setTName(followrQuestionMain.getTName());
        resp.setQaList(qaListRespList);
        return resp;
    }
}
